import { useEffect, useState, createContext, useContext } from 'react';
import {
  useUser as useSupaUser,
  useSessionContext,
  User
} from '@supabase/auth-helpers-react';

import { UserDetails, Subscription } from '@/types';

type UserContextType = {
  accessToken: string | null;
  user: User | null;
  userDetails: UserDetails | null;
  isLoading: boolean;
  subscription: Subscription | null;
};

//创建User对象相关的上下文对象,以便组件能够提供和读取。
export const UserContext = createContext<UserContextType | undefined>(undefined);

export interface Props {
  [propName: string]: any;
}

export const MyUserContextProvider = (props: Props) => {
  //获取<SupabaseProvider>组件提供的用户校验的响应式数据
  const {
    session,
    isLoading: isLoadingUser,
    supabaseClient: supabase
  } = useSessionContext();

  const user = useSupaUser();
  const accessToken = session?.access_token ?? null;
  const [isLoadingData, setIsloadingData] = useState(false);
  const [userDetails, setUserDetails] = useState<UserDetails | null>(null);
  const [subscription, setSubscription] = useState<Subscription | null>(null);

  //向数据库发起数据请求
  //getUserDetails和getSubscription仍然是一个异步函数
  const getUserDetails = () => supabase
    .from('users')
    .select('*')
    .single();

  const getSubscription = () => supabase
    .from('subscriptions')
    .select('*, price(*, products(*))')
    .in('status', ['trialing', 'active'])
    .single();
  
  useEffect(() => {
    if (user && !isLoadingData && !userDetails && !subscription) {
      setIsloadingData(true);
      Promise.allSettled([
        getUserDetails(), 
        getSubscription()
      ]).then(
        (results) => {
          /**
           console.log(results);
           * [
              {
                "status": "fulfilled",
                "value": {
                    "error": null,
                    "data": {
                        "id": "f7a860af-aa2e-4c68-abd4-aadc68c9c8f6",
                        "full_name": null,
                        "avatar_url": null,
                        "billing_address": null,
                        "payment_method": null
                    },
                    "count": null,
                    "status": 200,
                    "statusText": ""
                }
              },
              {
                "status": "fulfilled",
                "value": {
                    "error": {
                        "code": "PGRST200",
                        "details": "Searched for a foreign key relationship between 'subscriptions' and 'price' in the schema 'public', but no matches were found.",
                        "hint": "Perhaps you meant 'prices' instead of 'price'.",
                        "message": "Could not find a relationship between 'subscriptions' and 'price' in the schema cache"
                    },
                    "data": null,
                    "count": null,
                    "status": 400,
                    "statusText": ""
                }
              }
          ]
           */
          
          const userDetailsPromise = results[0];
          const subscriptionPromise = results[1];

          if (userDetailsPromise.status === 'fulfilled')
            setUserDetails(userDetailsPromise.value.data as UserDetails);

          if (subscriptionPromise.status === 'fulfilled')
            setSubscription(subscriptionPromise.value.data as Subscription);

          setIsloadingData(false);
        }
      );
    } else if (!user && !isLoadingUser && !isLoadingData) {
      setUserDetails(null);
      setSubscription(null);
    }
  }, [user, isLoadingUser]);

  const value = {
    accessToken,
    user,
    userDetails,
    isLoading: isLoadingUser || isLoadingData,
    subscription
  }

  /**
   console.log(value);
   * {accessToken: null, user: null, userDetails: null, isLoading: false, subscription: null}
   */
  

  return <UserContext.Provider value={value} {...props}/>;
}

//创建一个useUser的hook。
export const useUser = () => {
  //useContext()接受上下文对象（从 React.createContext 返回的值）并返回当前上下文值，由给定上下文的最近上下文提供者给出。
  const context = useContext(UserContext);
  
  if (context === undefined) {
    throw new Error(`useUser must be used within a MyUserContextProvider.`);
  }
  return context;
}


